/*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
*/
package gov.wa.wsdot.mobile.client.activities.home;
import com.google.code.gwt.database.client.GenericRow;
import com.google.code.gwt.database.client.service.DataServiceException;
import com.google.code.gwt.database.client.service.ListCallback;
import com.google.code.gwt.database.client.service.RowIdListCallback;
import com.google.code.gwt.database.client.service.VoidCallback;
import com.google.gwt.core.client.JsArray;
import com.google.gwt.core.client.JsArrayInteger;
import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.json.client.JSONArray;
import com.google.gwt.jsonp.client.JsonpRequestBuilder;
import com.google.gwt.regexp.shared.MatchResult;
import com.google.gwt.regexp.shared.RegExp;
import com.google.gwt.resources.client.ImageResource;
import com.google.gwt.storage.client.Storage;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.AbstractImagePrototype;
import com.google.gwt.user.client.ui.AcceptsOneWidget;
import com.google.web.bindery.event.shared.EventBus;
import com.googlecode.gwtphonegap.client.PhoneGap;
import com.googlecode.gwtphonegap.client.notification.AlertCallback;
import com.googlecode.gwtphonegap.client.notification.PromptCallback;
import com.googlecode.gwtphonegap.client.notification.PromptResults;
import com.googlecode.mgwt.mvp.client.MGWTAbstractActivity;
import com.googlecode.mgwt.ui.client.widget.panel.pull.PullArrowStandardHandler;
import com.googlecode.mgwt.ui.client.widget.panel.pull.PullArrowStandardHandler.PullActionHandler;
import gov.wa.wsdot.mobile.client.ClientFactory;
import gov.wa.wsdot.mobile.client.activities.about.AboutPlace;
import gov.wa.wsdot.mobile.client.activities.alert.AlertPlace;
import gov.wa.wsdot.mobile.client.activities.amtrakcascades.AmtrakCascadesPlace;
import gov.wa.wsdot.mobile.client.activities.borderwait.BorderWaitPlace;
import gov.wa.wsdot.mobile.client.activities.camera.CameraPlace;
import gov.wa.wsdot.mobile.client.activities.ferries.FerriesPlace;
import gov.wa.wsdot.mobile.client.activities.ferries.schedules.sailings.FerriesRouteSailingsPlace;
import gov.wa.wsdot.mobile.client.activities.mountainpasses.MountainPassDetailsPlace;
import gov.wa.wsdot.mobile.client.activities.mountainpasses.MountainPassesPlace;
import gov.wa.wsdot.mobile.client.activities.socialmedia.SocialMediaPlace;
import gov.wa.wsdot.mobile.client.activities.tollrates.TollRatesPlace;
import gov.wa.wsdot.mobile.client.activities.trafficmap.TrafficMapPlace;
import gov.wa.wsdot.mobile.client.activities.trafficmap.menu.traveltimes.TravelTimeDetailsPlace;
import gov.wa.wsdot.mobile.client.css.AppBundle;
import gov.wa.wsdot.mobile.client.plugins.accessibility.Accessibility;
import gov.wa.wsdot.mobile.client.plugins.analytics.Analytics;
import gov.wa.wsdot.mobile.client.service.WSDOTContract.*;
import gov.wa.wsdot.mobile.client.service.WSDOTDataService;
import gov.wa.wsdot.mobile.client.service.WSDOTDataService.Tables;
import gov.wa.wsdot.mobile.client.util.Consts;
import gov.wa.wsdot.mobile.shared.*;
import gov.wa.wsdot.mobile.shared.MountainPassConditions.Forecast;
import java.util.*;
import java.util.Map.Entry;
public class HomeActivity extends MGWTAbstractActivity implements
HomeView.Presenter {
private final ClientFactory clientFactory;
private final HomeView view;
private WSDOTDataService dbService;
private PhoneGap phoneGap;
private Analytics analytics;
private static final String HIGHWAY_ALERTS_URL = Consts.HOST_URL + "/traveler/api/highwayalerts";
private static final String FERRIES_SCHEDULES_URL = Consts.HOST_URL + "/traveler/api/wsfschedule";
private static final String MOUNTAIN_PASS_URL = Consts.HOST_URL + "/traveler/api/mountainpassconditions";
private static final String TRAVEL_TIMES_URL = Consts.HOST_URL + "/traveler/api/traveltimes";
private Accessibility accessibility;
private static List<LocationItem> locationItems = new ArrayList<LocationItem>();
private static List<CameraItem> cameraItems = new ArrayList<CameraItem>();
private static List<FerriesRouteItem> ferriesRouteItems = new ArrayList<FerriesRouteItem>();
private static List<MountainPassItem> mountainPassItems = new ArrayList<MountainPassItem>();
private static List<TravelTimesItem> travelTimesItems = new ArrayList<TravelTimesItem>();
private static List<HighwayAlertItem> highwayAlertItems = new ArrayList<HighwayAlertItem>();
private static Timer timer;
private static DateTimeFormat dateFormat = DateTimeFormat.getFormat("MMMM d, yyyy h:mm a");
private static DateTimeFormat parseDateFormat = DateTimeFormat.getFormat("yyyy,M,d,H,m"); //e.g. [2010, 11, 2, 8, 22]
private static HashMap<String, String[]> weatherPhrases = new HashMap<String, String[]>();
private static HashMap<String, String[]> weatherPhrasesNight = new HashMap<String, String[]>();
private static Storage localStorage = Storage.getLocalStorageIfSupported();
private static int lastTab = 0;
public HomeActivity(ClientFactory clientFactory) {
this.clientFactory = clientFactory;
view = clientFactory.getHomeView();
if (clientFactory.getPlaceController().getWhere() instanceof HomePlace) {
HomePlace homePlace = (HomePlace) clientFactory.getPlaceController().getWhere();
view.getTabPanel().setSelectedChild(homePlace.tabIndex);
}
}
@Override
public void start(AcceptsOneWidget panel, EventBus eventBus) {
view.setPresenter(this);
dbService = clientFactory.getDbService();
phoneGap = clientFactory.getPhoneGap();
analytics = clientFactory.getAnalytics();
accessibility = clientFactory.getAccessibility();
view.getPullHeader().setHTML("pull down");
PullArrowStandardHandler headerHandler = new PullArrowStandardHandler(
view.getPullHeader(), view.getPullPanel());
headerHandler.setErrorText("Error");
headerHandler.setLoadingText("Loading");
headerHandler.setNormalText("pull down");
headerHandler.setPulledText("release to load");
headerHandler.setPullActionHandler(new PullActionHandler() {
@Override
public void onPullAction(final AsyncCallback<Void> callback) {
new Timer() {
@Override
public void run() {
createFavoritesList();
view.refresh();
callback.onSuccess(null);
}
}.schedule(1);
}
});
view.setHeaderPullHandler(headerHandler);
buildWeatherPhrases();
createAlertsList();
createFavoritesList();
timer = new Timer() {
@Override
public void run() {
createAlertsList();
}
};
// Schedule alert box to update every 60 seconds (60000 millseconds).
timer.scheduleRepeating(60000);
if (Consts.ANALYTICS_ENABLED) {
analytics.trackScreen("/Home");
}
panel.setWidget(view);
accessibility.postScreenChangeNotification();
}
private void createAlertsList() {
/**
* Check the cache table for the last time data was downloaded. If we are within
* the allowed time period, don't sync, otherwise get fresh data from the server.
*/
dbService.getCacheLastUpdated(Tables.HIGHWAY_ALERTS, new ListCallback<GenericRow>() {
@Override
public void onFailure(DataServiceException error) {
// On first install the 'caches' table doesn't exist yet. Why?
highwayAlertItems.clear();
highwayAlertItems.add(new HighwayAlertItem(-1, "No highest impact travel alerts"));
view.hideProgressIndicator();
view.render(highwayAlertItems);
view.refresh();
}
@Override
public void onSuccess(List<GenericRow> result) {
boolean shouldUpdate = true;
if (!result.isEmpty()) {
double now = System.currentTimeMillis();
double lastUpdated = result.get(0).getDouble(CachesColumns.CACHE_LAST_UPDATED);
shouldUpdate = (Math.abs(now - lastUpdated) > (5 * 60000)); // Refresh every 5 minutes.
}
view.showProgressIndicator();
view.clear();
if (shouldUpdate) {
try {
JsonpRequestBuilder jsonp = new JsonpRequestBuilder();
// Set timeout for 30 seconds (30000 milliseconds)
jsonp.setTimeout(30000);
jsonp.requestObject(HIGHWAY_ALERTS_URL, new AsyncCallback<HighwayAlerts>() {
@Override
public void onFailure(Throwable caught) {
highwayAlertItems.clear();
highwayAlertItems.add(new HighwayAlertItem(-1, "Can't load data. Check your connection."));
view.hideProgressIndicator();
view.render(highwayAlertItems);
view.refresh();
}
@Override
public void onSuccess(HighwayAlerts result) {
highwayAlertItems.clear();
if (result.getAlerts() != null) {
HighwayAlertItem item;
int size = result.getAlerts().getItems().length();
for (int i = 0; i < size; i++) {
item = new HighwayAlertItem();
item.setAlertId(result.getAlerts().getItems().get(i).getAlertID());
item.setHeadlineDescription(result.getAlerts().getItems().get(i).getHeadlineDescription());
item.setEventCategory(result.getAlerts().getItems().get(i).getEventCategory());
item.setPriority(result.getAlerts().getItems().get(i).getPriority());
item.setStartLatitude(result.getAlerts().getItems().get(i).getStartRoadwayLocation().getLatitude());
item.setStartLongitude(result.getAlerts().getItems().get(i).getStartRoadwayLocation().getLongitude());
item.setStartRoadName(result.getAlerts().getItems().get(i).getStartRoadwayLocation().getRoadName());
item.setLastUpdatedTime(dateFormat.format(new Date(
Long.parseLong(result
.getAlerts()
.getItems()
.get(i)
.getLastUpdatedTime()
.substring(6, 19)))));
highwayAlertItems.add(item);
}
// Purge existing highway alerts covered by incoming data
dbService.deleteHighwayAlerts(new VoidCallback() {
@Override
public void onFailure(DataServiceException error) {
}
@Override
public void onSuccess() {
// Bulk insert all the new highway alerts
dbService.insertHighwayAlerts(highwayAlertItems, new RowIdListCallback() {
@Override
public void onFailure(DataServiceException error) {
highwayAlertItems.clear();
highwayAlertItems.add(new HighwayAlertItem(-1, error.getMessage()));
view.hideProgressIndicator();
view.render(highwayAlertItems);
view.refresh();
}
@Override
public void onSuccess(List<Integer> rowIds) {
// Update the cache table with the time we did the update
List<CacheItem> cacheItems = new ArrayList<CacheItem>();
cacheItems.add(new CacheItem(Tables.HIGHWAY_ALERTS, System.currentTimeMillis()));
dbService.updateCachesTable(cacheItems, new VoidCallback() {
@Override
public void onFailure(DataServiceException error) {
}
@Override
public void onSuccess() {
dbService.getHighwayAlerts(new ListCallback<GenericRow>() {
@Override
public void onFailure(DataServiceException error) {
}
@Override
public void onSuccess(List<GenericRow> result) {
getHighestPriorityHighwayAlerts(result);
}
});
}
});
}
});
}
});
}
}
});
} catch (Exception e) {
}
} else {
dbService.getHighwayAlerts(new ListCallback<GenericRow>() {
@Override
public void onFailure(DataServiceException error) {
}
@Override
public void onSuccess(List<GenericRow> result) {
getHighestPriorityHighwayAlerts(result);
}
});
}
}
});
}
private void getHighestPriorityHighwayAlerts(List<GenericRow> result) {
highwayAlertItems.clear();
HighwayAlertItem item;
int numResults = result.size();
for (int i = 0; i < numResults; i++) {
if (result.get(i).getString(HighwayAlertsColumns.HIGHWAY_ALERT_PRIORITY).equalsIgnoreCase("highest")) {
item = new HighwayAlertItem();
item.setAlertId(result.get(i).getInt(HighwayAlertsColumns.HIGHWAY_ALERT_ID));
item.setHeadlineDescription(result.get(i).getString(HighwayAlertsColumns.HIGHWAY_ALERT_HEADLINE));
highwayAlertItems.add(item);
}
}
if (highwayAlertItems.isEmpty()) {
highwayAlertItems.add(new HighwayAlertItem(-1, "No highest impact travel alerts"));
}
view.hideProgressIndicator();
view.render(highwayAlertItems);
view.refresh();
}
@Override
public void onStop() {
timer.cancel();
view.setPresenter(null);
}
@Override
public void onAboutButtonPressed() {
clientFactory.getPlaceController().goTo(new AboutPlace());
}
@Override
public void onTrafficMapButtonPressed() {
clientFactory.getPlaceController().goTo(new TrafficMapPlace());
}
@Override
public void onFerriesButtonPressed() {
clientFactory.getPlaceController().goTo(new FerriesPlace());
}
@Override
public void onMountainPassesButtonPressed() {
clientFactory.getPlaceController().goTo(new MountainPassesPlace());
}
@Override
public void onSocialMediaButtonPressed() {
clientFactory.getPlaceController().goTo(new SocialMediaPlace());
}
@Override
public void onTollRatesButtonPressed() {
clientFactory.getPlaceController().goTo(new TollRatesPlace());
}
@Override
public void onBorderWaitButtonPressed() {
clientFactory.getPlaceController().goTo(new BorderWaitPlace());
}
@Override
public void onAmtrakButtonPressed() {
clientFactory.getPlaceController().goTo(new AmtrakCascadesPlace());
}
@Override
public void onHighImpactAlertSelected(int alertId) {
clientFactory.getPlaceController().goTo(
new AlertPlace(Integer.toString(alertId)));
}
private void createFavoritesList() {
getFavoriteLocations();
dbService.getStarredCameras(new ListCallback<GenericRow>() {
@Override
public void onFailure(DataServiceException error) {
}
@Override
public void onSuccess(List<GenericRow> result) {
if (!result.isEmpty()) {
cameraItems.clear();
CameraItem c;
for (GenericRow camera: result) {
c = new CameraItem();
c.setCameraId(camera.getInt(CamerasColumns.CAMERA_ID));
c.setTitle(camera.getString(CamerasColumns.CAMERA_TITLE));
cameraItems.add(c);
}
view.hideEmptyFavoritesMessage();
view.showCamerasHeader();
view.showCamerasList();
view.renderCameras(cameraItems);
view.refresh();
accessibility.postScreenChangeNotification();
} else {
view.hideCamerasHeader();
view.hideCamerasList();
}
}
});
dbService.getStarredFerriesSchedules(new ListCallback<GenericRow>() {
@Override
public void onFailure(DataServiceException error) {
}
@Override
public void onSuccess(final List<GenericRow> starredFerriesSchedules) {
if (!starredFerriesSchedules.isEmpty()) {
/**
* Check the cache table for the last time data was downloaded. If we are within
* the allowed time period, don't sync, otherwise get fresh data from the server.
*/
dbService.getCacheLastUpdated(Tables.FERRIES_SCHEDULES, new ListCallback<GenericRow>() {
@Override
public void onFailure(DataServiceException error) {
}
@Override
public void onSuccess(List<GenericRow> result) {
boolean shouldUpdate = true;
if (!result.isEmpty()) {
double now = System.currentTimeMillis();
double lastUpdated = result.get(0).getDouble(CachesColumns.CACHE_LAST_UPDATED);
shouldUpdate = (Math.abs(now - lastUpdated) > (30 * 60000)); // Refresh every 30 minutes.
}
//view.showProgressBar();
if (shouldUpdate) {
final List<Integer> starred = new ArrayList<Integer>();
for (GenericRow row: starredFerriesSchedules) {
starred.add(row.getInt(FerriesSchedulesColumns.FERRIES_SCHEDULE_ID));
}
JsonpRequestBuilder jsonp = new JsonpRequestBuilder();
// Set timeout for 30 seconds (30000 milliseconds)
jsonp.setTimeout(30000);
jsonp.requestObject(
FERRIES_SCHEDULES_URL,
new AsyncCallback<FerriesRouteFeed>() {
@Override
public void onFailure(Throwable caught) {
//view.hideProgressBar();
phoneGap.getNotification()
.alert("Can't load data. Check your connection.",
new AlertCallback() {
@Override
public void onOkButtonClicked() {
// TODO Auto-generated method stub
}
}, "Connection Error");
}
@Override
public void onSuccess(FerriesRouteFeed result) {
if (result.getRoutes() != null) {
ferriesRouteItems.clear();
FerriesRouteItem item;
int numRoutes = result.getRoutes().length();
for (int i = 0; i < numRoutes; i++) {
item = new FerriesRouteItem();
item.setRouteID(result.getRoutes().get(i).getRouteID());
item.setDescription(result.getRoutes().get(i).getDescription());
item.setCrossingTime(result.getRoutes().get(i).getCrossingTime());
item.setScheduleDate(new JSONArray(result.getRoutes().get(i).getDate()).toString());
item.setRouteAlert(new JSONArray(result.getRoutes().get(i).getRouteAlert()).toString());
item.setCacheDate(dateFormat.format(new Date(
Long.parseLong(result.getRoutes()
.get(i).getCacheDate()
.substring(6, 19)))));
if (starred.contains(result.getRoutes().get(i).getRouteID())) {
item.setIsStarred(1);
}
ferriesRouteItems.add(item);
}
// Purge existing border wait times covered by incoming data
dbService.deleteFerriesSchedules(new VoidCallback() {
@Override
public void onFailure(DataServiceException error) {
}
@Override
public void onSuccess() {
// Bulk insert all the new ferries schedules
dbService.insertFerriesSchedules(ferriesRouteItems, new RowIdListCallback() {
@Override
public void onFailure(DataServiceException error) {
}
@Override
public void onSuccess(List<Integer> rowIds) {
// Update the cache table with the time we did the update
List<CacheItem> cacheItems = new ArrayList<CacheItem>();
cacheItems.add(new CacheItem(Tables.FERRIES_SCHEDULES, System.currentTimeMillis()));
dbService.updateCachesTable(cacheItems, new VoidCallback() {
@Override
public void onFailure(DataServiceException error) {
}
@Override
public void onSuccess() {
dbService.getStarredFerriesSchedules(new ListCallback<GenericRow>() {
@Override
public void onFailure(DataServiceException error) {}
@Override
public void onSuccess(final List<GenericRow> starredMountainPassRows) {
getFerriesSchedules(starredFerriesSchedules);
}
});
}
});
}
});
}
});
}
}
});
} else {
getFerriesSchedules(starredFerriesSchedules);
}
}
});
} else {
view.hideFerriesHeader();
view.hideFerriesList();
}
}
});
dbService.getStarredMountainPasses(new ListCallback<GenericRow>() {
@Override
public void onFailure(DataServiceException error) {
}
@Override
public void onSuccess(final List<GenericRow> starredMountainPassRows) {
if (!starredMountainPassRows.isEmpty()) {
/**
* Check the cache table for the last time data was downloaded. If we are within
* the allowed time period, don't sync, otherwise get fresh data from the server.
*/
dbService.getCacheLastUpdated(Tables.MOUNTAIN_PASSES, new ListCallback<GenericRow>() {
@Override
public void onFailure(DataServiceException error) {
}
@Override
public void onSuccess(List<GenericRow> result) {
boolean shouldUpdate = true;
if (!result.isEmpty()) {
double now = System.currentTimeMillis();
double lastUpdated = result.get(0).getDouble(CachesColumns.CACHE_LAST_UPDATED);
shouldUpdate = (Math.abs(now - lastUpdated) > (15 * 60000)); // Refresh every 15 minutes.
}
//view.showProgressBar();
if (shouldUpdate) {
final List<Integer> starred = new ArrayList<Integer>();
for (GenericRow row: starredMountainPassRows) {
starred.add(row.getInt(MountainPassesColumns.MOUNTAIN_PASS_ID));
}
JsonpRequestBuilder jsonp = new JsonpRequestBuilder();
// Set timeout for 30 seconds (30000 milliseconds)
jsonp.setTimeout(30000);
jsonp.requestObject(
MOUNTAIN_PASS_URL,
new AsyncCallback<MountainPassConditions>() {
@Override
public void onFailure(Throwable caught) {
//view.hideProgressBar();
phoneGap.getNotification()
.alert("Can't load data. Check your connection.",
new AlertCallback() {
@Override
public void onOkButtonClicked() {
// TODO Auto-generated method stub
}
}, "Connection Error");
}
@Override
public void onSuccess(MountainPassConditions result) {
mountainPassItems.clear();
if (result.getMountainPassConditionsResult() != null) {
MountainPassItem item;
String weatherCondition;
String weatherImage;
String forecast_weather_image;
String mDateUpdated = "";
int numConditions = result.getMountainPassConditionsResult().getPassCondition().length();
for (int i = 0; i < numConditions; i++) {
item = new MountainPassItem();
weatherCondition = result.getMountainPassConditionsResult().getPassCondition().get(i).getWeatherCondition();
weatherImage = getWeatherImage(weatherPhrases, weatherCondition);
JsArrayInteger dateUpdated = result.getMountainPassConditionsResult().getPassCondition().get(i).getDateUpdated();
try {
StringBuilder sb = new StringBuilder();
for (int j=0; j < 5; j++) {
sb.append(dateUpdated.get(j));
sb.append(",");
}
String tempDate = sb.toString().trim();
tempDate = tempDate.substring(0, tempDate.length()-1);
Date date = parseDateFormat.parse(tempDate);
mDateUpdated = dateFormat.format(date);
} catch (Exception e) {
mDateUpdated = "N/A";
}
JsArray<Forecast> forecasts = result.getMountainPassConditionsResult().getPassCondition().get(i).getForecast();
int numForecasts = forecasts.length();
for (int k=0; k < numForecasts; k++) {
Forecast forecast = forecasts.get(k);
if (isNight(forecast.getDay())) {
forecast_weather_image = getWeatherImage(weatherPhrasesNight, forecast.getForecastText());
} else {
forecast_weather_image = getWeatherImage(weatherPhrases, forecast.getForecastText());
}
forecast.setWeatherIcon(forecast_weather_image);
if (k == 0) {
if (weatherCondition.equals("")) {
weatherCondition = forecast.getForecastText().split("\\.")[0] + ".";
weatherImage = forecast_weather_image;
}
}
forecasts.set(k, forecast);
}
item.setWeatherCondition(weatherCondition);
item.setElevationInFeet(result.getMountainPassConditionsResult().getPassCondition().get(i).getElevationInFeet());
item.setMountainPassId(result.getMountainPassConditionsResult().getPassCondition().get(i).getMountainPassId());
item.setRoadCondition(result.getMountainPassConditionsResult().getPassCondition().get(i).getRoadCondition());
item.setTemperatureInFahrenheit(result.getMountainPassConditionsResult().getPassCondition().get(i).getTemperatureInFahrenheit());
item.setDateUpdated(mDateUpdated);
item.setMountainPassName(result.getMountainPassConditionsResult().getPassCondition().get(i).getMountainPassName());
item.setWeatherIcon(weatherImage);
item.setRestrictionOneText(result.getMountainPassConditionsResult().getPassCondition().get(i).getRestrictionOne().getRestrictionText());
item.setRestrictionOneTravelDirection(result.getMountainPassConditionsResult().getPassCondition().get(i).getRestrictionOne().getTravelDirection());
item.setRestrictionTwoText(result.getMountainPassConditionsResult().getPassCondition().get(i).getRestrictionTwo().getRestrictionText());
item.setRestrictionTwoTravelDirection(result.getMountainPassConditionsResult().getPassCondition().get(i).getRestrictionTwo().getTravelDirection());
item.setCamera(new JSONArray(result.getMountainPassConditionsResult().getPassCondition().get(i).getCameras()).toString());
item.setForecast(new JSONArray(forecasts).toString());
if (starred.contains(result.getMountainPassConditionsResult().getPassCondition().get(i).getMountainPassId())) {
item.setIsStarred(1);
}
mountainPassItems.add(item);
}
// Purge existing mountain passes covered by incoming data
dbService.deleteMountainPasses(new VoidCallback() {
@Override
public void onFailure(DataServiceException error) {
}
@Override
public void onSuccess() {
// Bulk insert all the new mountain passes
dbService.insertMountainPasses(mountainPassItems, new RowIdListCallback() {
@Override
public void onFailure(DataServiceException error) {
}
@Override
public void onSuccess(List<Integer> rowIds) {
// Update the cache table with the time we did the update
ArrayList<CacheItem> cacheItems = new ArrayList<CacheItem>();
cacheItems.add(new CacheItem(Tables.MOUNTAIN_PASSES, System.currentTimeMillis()));
dbService.updateCachesTable(cacheItems, new VoidCallback() {
@Override
public void onFailure(DataServiceException error) {
}
@Override
public void onSuccess() {
dbService.getStarredMountainPasses(new ListCallback<GenericRow>() {
@Override
public void onFailure(DataServiceException error) {}
@Override
public void onSuccess(final List<GenericRow> starredMountainPassRows) {
getMountainPasses(starredMountainPassRows);
}
});
}
});
}
});
}
});
}
}
});
} else {
getMountainPasses(starredMountainPassRows);
}
}
});
} else {
view.hideMountainPassesHeader();
view.hideMountainPassesList();
}
}
});
dbService.getStarredTravelTimes(new ListCallback<GenericRow>() {
@Override
public void onFailure(DataServiceException error) {
}
@Override
public void onSuccess(final List<GenericRow> starredTravelTimesRows) {
if (!starredTravelTimesRows.isEmpty()) {
/**
* Check the cache table for the last time data was downloaded. If we are within
* the allowed time period, don't sync, otherwise get fresh data from the server.
*/
dbService.getCacheLastUpdated(Tables.TRAVEL_TIMES, new ListCallback<GenericRow>() {
@Override
public void onFailure(DataServiceException error) {
}
@Override
public void onSuccess(List<GenericRow> result) {
boolean shouldUpdate = true;
if (!result.isEmpty()) {
double now = System.currentTimeMillis();
double lastUpdated = result.get(0).getDouble(CachesColumns.CACHE_LAST_UPDATED);
shouldUpdate = (Math.abs(now - lastUpdated) > (5 * 60000)); // Refresh every 5 minutes.
}
//view.showProgressBar();
if (shouldUpdate) {
final List<Integer> starred = new ArrayList<Integer>();
for (GenericRow row: starredTravelTimesRows) {
starred.add(row.getInt(TravelTimesColumns.TRAVEL_TIMES_ID));
}
JsonpRequestBuilder jsonp = new JsonpRequestBuilder();
// Set timeout for 30 seconds (30000 milliseconds)
jsonp.setTimeout(30000);
jsonp.requestObject(TRAVEL_TIMES_URL, new AsyncCallback<TravelTimes>() {
@Override
public void onFailure(Throwable caught) {
//view.hideProgressBar();
phoneGap.getNotification()
.alert("Can't load data. Check your connection.",
new AlertCallback() {
@Override
public void onOkButtonClicked() {
// TODO Auto-generated method stub
}
}, "Connection Error");
}
@Override
public void onSuccess(TravelTimes result) {
if (result.getTravelTimes() != null) {
travelTimesItems.clear();
TravelTimesItem item ;
int numItems = result.getTravelTimes().getItems().length();
for (int i = 0; i < numItems; i++) {
item = new TravelTimesItem();
item.setDistance(result.getTravelTimes().getItems().get(i).getDistance());
item.setUpdated(result.getTravelTimes().getItems().get(i).getUpdated());
item.setTitle(result.getTravelTimes().getItems().get(i).getTitle());
item.setAverageTime(result.getTravelTimes().getItems().get(i).getAverage());
item.setRouteId(Integer.parseInt(result.getTravelTimes().getItems().get(i).getRouteId(), 10));
item.setCurrentTime(result.getTravelTimes().getItems().get(i).getCurrent());
if (starred.contains(Integer.parseInt(result.getTravelTimes().getItems().get(i).getRouteId(), 10))) {
item.setIsStarred(1);
}
travelTimesItems.add(item);
}
// Purge existing mountain passes covered by incoming data
dbService.deleteTravelTimes(new VoidCallback() {
@Override
public void onFailure(DataServiceException error) {
}
@Override
public void onSuccess() {
// Bulk insert all the new travel times
dbService.insertTravelTimes(travelTimesItems, new RowIdListCallback() {
@Override
public void onFailure(DataServiceException error) {
}
@Override
public void onSuccess(List<Integer> rowIds) {
// Update the cache table with the time we did the update
ArrayList<CacheItem> cacheItems = new ArrayList<CacheItem>();
cacheItems.add(new CacheItem(Tables.TRAVEL_TIMES, System.currentTimeMillis()));
dbService.updateCachesTable(cacheItems, new VoidCallback() {
@Override
public void onFailure(DataServiceException error) {
}
@Override
public void onSuccess() {
dbService.getStarredTravelTimes(new ListCallback<GenericRow>() {
@Override
public void onFailure(DataServiceException error) {}
@Override
public void onSuccess(final List<GenericRow> starredMountainPassRows) {
getTravelTimes(starredTravelTimesRows);
}
});
}
});
}
});
}
});
}
}
});
} else {
getTravelTimes(starredTravelTimesRows);
}
}
});
} else {
view.hideTravelTimesHeader();
view.hideTravelTimesList();
}
}
});
view.showEmptyFavoritesMessage();
}
private void getFavoriteLocations(){
dbService.getLocations(new ListCallback<GenericRow>() {
@Override
public void onFailure(DataServiceException error) {
}
@Override
public void onSuccess(List<GenericRow> result) {
if (!result.isEmpty()) {
locationItems.clear();
LocationItem l;
for (GenericRow location: result) {
l = new LocationItem(location.getInt(LocationColumns._ID),
location.getString(LocationColumns.LOCATION_TITLE),
location.getDouble(LocationColumns.LOCATION_LAT),
location.getDouble(LocationColumns.LOCATION_LONG),
location.getInt(LocationColumns.LOCATION_ZOOM));
locationItems.add(l);
}
view.hideEmptyFavoritesMessage();
view.showLocationsHeader();
view.showLocationsList();
view.renderLocations(locationItems);
view.refresh();
accessibility.postScreenChangeNotification();
} else {
view.hideLocationsHeader();
view.hideLocationsList();
}
}
});
}
private void getFerriesSchedules(List<GenericRow> result) {
ferriesRouteItems.clear();
FerriesRouteItem f;
for (GenericRow route: result) {
f = new FerriesRouteItem();
f.setRouteID(route.getInt(FerriesSchedulesColumns.FERRIES_SCHEDULE_ID));
f.setDescription(route.getString(FerriesSchedulesColumns.FERRIES_SCHEDULE_TITLE));
f.setCrossingTime(route.getString(FerriesSchedulesColumns.FERRIES_SCHEDULE_CROSSING_TIME));
f.setRouteAlert(route.getString(FerriesSchedulesColumns.FERRIES_SCHEDULE_ALERT));
f.setCacheDate(route.getString(FerriesSchedulesColumns.FERRIES_SCHEDULE_UPDATED));
ferriesRouteItems.add(f);
}
view.hideEmptyFavoritesMessage();
view.showFerriesHeader();
view.showFerriesList();
view.renderFerries(ferriesRouteItems);
view.refresh();
accessibility.postScreenChangeNotification();
}
private void getMountainPasses(List<GenericRow> result) {
mountainPassItems.clear();
MountainPassItem m;
for (GenericRow pass: result) {
m = new MountainPassItem();
m.setMountainPassId(pass.getInt(MountainPassesColumns.MOUNTAIN_PASS_ID));
m.setMountainPassName(pass.getString(MountainPassesColumns.MOUNTAIN_PASS_NAME));
m.setWeatherIcon(pass.getString(MountainPassesColumns.MOUNTAIN_PASS_WEATHER_ICON));
m.setWeatherCondition(pass.getString(MountainPassesColumns.MOUNTAIN_PASS_WEATHER_CONDITION));
m.setDateUpdated(pass.getString(MountainPassesColumns.MOUNTAIN_PASS_DATE_UPDATED));
mountainPassItems.add(m);
}
view.hideEmptyFavoritesMessage();
view.showMountainPassesHeader();
view.showMountainPassesList();
view.renderMountainPasses(mountainPassItems);
view.refresh();
accessibility.postScreenChangeNotification();
}
private void getTravelTimes(List<GenericRow> result) {
travelTimesItems.clear();
TravelTimesItem t;
for (GenericRow time: result) {
t = new TravelTimesItem();
t.setRouteId(time.getInt(TravelTimesColumns.TRAVEL_TIMES_ID));
t.setTitle(time.getString(TravelTimesColumns.TRAVEL_TIMES_TITLE));
t.setUpdated(time.getString(TravelTimesColumns.TRAVEL_TIMES_UPDATED));
t.setDistance(time.getString(TravelTimesColumns.TRAVEL_TIMES_DISTANCE));
t.setAverageTime(time.getInt(TravelTimesColumns.TRAVEL_TIMES_AVERAGE));
t.setCurrentTime(time.getInt(TravelTimesColumns.TRAVEL_TIMES_CURRENT));
travelTimesItems.add(t);
}
view.hideEmptyFavoritesMessage();
view.showTravelTimesHeader();
view.showTravelTimesList();
view.renderTravelTimes(travelTimesItems);
view.refresh();
accessibility.postScreenChangeNotification();
}
@Override
public void onLocationSelected(int index){
if (Consts.ANALYTICS_ENABLED) {
analytics.trackScreen("/Favorites/Location");
}
LocationItem item = locationItems.get(index);
storeMapLocation(item.getLatitude(), item.getLongitude(), item.getZoom());
clientFactory.getPlaceController().goTo(
new TrafficMapPlace());
}
@Override
public void onLocationRemove(final int index) {
LocationItem item = locationItems.get(index);
dbService.removeLocation(item, new VoidCallback() {
@Override
public void onFailure(DataServiceException error) {}
@Override
public void onSuccess(){
// update view
locationItems.remove(index);
if (locationItems.size() == 0){
// TODO: Better way of displaying empty favorites when Location is only item
createFavoritesList();
}
view.renderLocations(locationItems);
}
});
}
@Override
public void onLocationEdit(final int index) {
phoneGap.getNotification().prompt(
"Enter new a name for this location.",
new PromptCallback() {
@Override
public void onPrompt(PromptResults results) {
if(results.getButtonIndex() == 2){
int id = locationItems.get(index).getId();
// Add location item to Database
dbService.editLocation(id, results.getInput1(), new VoidCallback() {
@Override
public void onFailure(DataServiceException error) {
phoneGap.getNotification().alert(
"Name could not be edited",
new AlertCallback() {
@Override
public void onOkButtonClicked() {
// TODO Auto-generated method stub
}
}, "Failed");
}
@Override
public void onSuccess(){
getFavoriteLocations();
view.renderLocations(locationItems);
}
});
}
}
},
"Edit Name",
locationItems.get(index).getTitle(),
new String[]{"Cancel","Ok"});
}
@Override
public void onCameraSelected(int index) {
if (Consts.ANALYTICS_ENABLED) {
analytics.trackScreen("/Favorites/Cameras");
}
CameraItem item = cameraItems.get(index);
clientFactory.getPlaceController().goTo(
new CameraPlace(Integer.toString(item.getCameraId())));
}
@Override
public void onFerriesSelected(int index) {
if (Consts.ANALYTICS_ENABLED) {
analytics.trackScreen("/Favorites/Ferries");
}
FerriesRouteItem item = ferriesRouteItems.get(index);
clientFactory.getPlaceController().goTo(
new FerriesRouteSailingsPlace(Integer.toString(item
.getRouteID())));
}
@Override
public void onMountainPassSelected(int index) {
if (Consts.ANALYTICS_ENABLED) {
analytics.trackScreen("/Favorites/Mountain Passes");
}
MountainPassItem item = mountainPassItems.get(index);
clientFactory.getPlaceController().goTo(
new MountainPassDetailsPlace(Integer.toString(item
.getMountainPassId())));
}
@Override
public void onTravelTimeSelected(int index) {
if (Consts.ANALYTICS_ENABLED) {
analytics.trackScreen("/Favorites/Travel Times");
}
TravelTimesItem item = travelTimesItems.get(index);
clientFactory.getPlaceController()
.goTo(new TravelTimeDetailsPlace(Integer.toString(item
.getRouteId())));
}
@Override
public void onTabSelected(int index) {
int currentTab = index;
if (clientFactory.getPlaceController().getWhere() instanceof HomePlace){
HomePlace homePlace = (HomePlace) clientFactory.getPlaceController().getWhere();
homePlace.tabIndex = index;
}
if ((currentTab != lastTab) && (currentTab == 1)){
if (Consts.ANALYTICS_ENABLED) {
analytics.trackScreen("/Favorites");
}
}
lastTab = currentTab;
}
@SuppressWarnings("unused")
private static String makeImage(ImageResource resource) {
AbstractImagePrototype image = AbstractImagePrototype.create(resource);
String html = image.getHTML();
return html;
}
private void buildWeatherPhrases() {
String[] weather_clear = {"fair", "sunny", "clear"};
String[] weather_few_clouds = {"few clouds", "scattered clouds", "mostly sunny", "mostly clear"};
String[] weather_partly_cloudy = {"partly cloudy", "partly sunny"};
String[] weather_cloudy = {"cloudy"};
String[] weather_mostly_cloudy = {"broken", "mostly cloudy"};
String[] weather_overcast = {"overcast"};
String[] weather_light_rain = {"occasional light rain", "light rain", "showers"};
String[] weather_rain = {"rain", "heavy rain", "raining"};
String[] weather_snow = {"snow", "snowing", "light snow", "heavy snow"};
String[] weather_fog = {"areas of fog", "fog"};
String[] weather_sleet = {"rain snow", "light rain snow", "heavy rain snow", "rain and snow"};
String[] weather_hail = {"ice pellets", "light ice pellets", "heavy ice pellets", "hail"};
String[] weather_thunderstorm = {"thunderstorm", "thunderstorms"};
weatherPhrases.clear();
weatherPhrasesNight.clear();
weatherPhrases.put(AppBundle.INSTANCE.css().sunnyIcon(), weather_clear);
weatherPhrases.put(AppBundle.INSTANCE.css().cloudy_1Icon(), weather_few_clouds);
weatherPhrases.put(AppBundle.INSTANCE.css().cloudy_2Icon(), weather_partly_cloudy);
weatherPhrases.put(AppBundle.INSTANCE.css().cloudy_3Icon(), weather_cloudy);
weatherPhrases.put(AppBundle.INSTANCE.css().cloudy_4Icon(), weather_mostly_cloudy);
weatherPhrases.put(AppBundle.INSTANCE.css().overcastIcon(), weather_overcast);
weatherPhrases.put(AppBundle.INSTANCE.css().light_rainIcon(), weather_light_rain);
weatherPhrases.put(AppBundle.INSTANCE.css().shower_3Icon(), weather_rain);
weatherPhrases.put(AppBundle.INSTANCE.css().snow_4Icon(), weather_snow);
weatherPhrases.put(AppBundle.INSTANCE.css().fogIcon(), weather_fog);
weatherPhrases.put(AppBundle.INSTANCE.css().sleetIcon(), weather_sleet);
weatherPhrases.put(AppBundle.INSTANCE.css().hailIcon(), weather_hail);
weatherPhrases.put(AppBundle.INSTANCE.css().tstorm_3Icon(), weather_thunderstorm);
weatherPhrasesNight.put(AppBundle.INSTANCE.css().sunny_nightIcon(), weather_clear);
weatherPhrasesNight.put(AppBundle.INSTANCE.css().cloudy_1_nightIcon(), weather_few_clouds);
weatherPhrasesNight.put(AppBundle.INSTANCE.css().cloudy_2_nightIcon(), weather_partly_cloudy);
weatherPhrasesNight.put(AppBundle.INSTANCE.css().cloudy_3_nightIcon(), weather_cloudy);
weatherPhrasesNight.put(AppBundle.INSTANCE.css().cloudy_4_nightIcon(), weather_mostly_cloudy);
weatherPhrasesNight.put(AppBundle.INSTANCE.css().overcastIcon(), weather_overcast);
weatherPhrasesNight.put(AppBundle.INSTANCE.css().light_rainIcon(), weather_light_rain);
weatherPhrasesNight.put(AppBundle.INSTANCE.css().shower_3Icon(), weather_rain);
weatherPhrasesNight.put(AppBundle.INSTANCE.css().snow_4Icon(), weather_snow);
weatherPhrasesNight.put(AppBundle.INSTANCE.css().fog_nightIcon(), weather_fog);
weatherPhrasesNight.put(AppBundle.INSTANCE.css().sleetIcon(), weather_sleet);
weatherPhrasesNight.put(AppBundle.INSTANCE.css().hailIcon(), weather_hail);
weatherPhrasesNight.put(AppBundle.INSTANCE.css().tstorm_3Icon(), weather_thunderstorm);
return;
}
private static String getWeatherImage(HashMap<String, String[]> weatherPhrases, String weather) {
String image = AppBundle.INSTANCE.css().weather_naIcon();
Set<Entry<String, String[]>> set = weatherPhrases.entrySet();
Iterator<Entry<String, String[]>> i = set.iterator();
if (weather.equals("")) return image;
String s0 = weather.split("\\.")[0]; // Pattern match on first sentence only.
while(i.hasNext()) {
Entry<String, String[]> me = i.next();
for (String phrase: (String[])me.getValue()) {
if (s0.toLowerCase().startsWith(phrase)) {
image = (String)me.getKey();
return image;
}
}
}
return image;
}
private static boolean isNight(String text) {
String patternStr = "night|tonight";
RegExp pattern = RegExp.compile(patternStr, "i");
MatchResult matcher = pattern.exec(text);
boolean matchFound = matcher != null;
return matchFound;
}
private void storeMapLocation(double latitude, double longitude, int zoom) {
if (localStorage != null) {
localStorage.setItem("KEY_MAP_LAT", String.valueOf(latitude));
localStorage.setItem("KEY_MAP_LON", String.valueOf(longitude));
localStorage.setItem("KEY_MAP_ZOOM", String.valueOf(zoom));
}
}
}